import axios from "axios";
import utils from "../utils";
import { Loading, MessageBox, Message } from "element-ui";
import imports from "@/http/service/imports";
import store from "@/store";
import { getrefsToken, getToken, setrefsToken, setToken } from "@/utils/auth";
class Axios {
  constructor() {
    this.loading = "";
    this.timer = "";
    this.needLoadingRequestCount = 0;
    // 不需要加载中的接口
    this.excludeUrls = ['chat/customer/user','store/settings/list','alliance/updown/allUnreadNum'];

    axios.defaults.baseURL = utils.BaseApi();
    axios.defaults.timeout = 60000;

    //避免重复刷新token
    this.isRefreshing = false
    this.pendingRequests = []

    this.RequestInterceptors();
    this.ResponseInterceptors();

    //this.instance 和 响应拦截器
    this.instance = axios.create({
      baseURL: utils.TokenBaseApi(),
      timeout: 10000,
    });
    this.tokenPostInterceptors();

    //pms呼叫服务
    this.chatAxios = axios.create({
      baseURL: utils.XZchatBaseApi(),
      timeout: 10000,
    })
    this.chatRequestInterceptors()
    this.chatResponseInterceptors()

    //导出Excel请求
    this.ExportAxios = axios.create({
      baseURL: utils.BaseApi(),
      timeout: 10000,
    });
  }

  startLoading() {
    //使用Element loading-start 方法
    this.loading = Loading.service({
      lock: true,
      text: "加载中...",
      background: "rgba(0, 0, 0, 0.1)",
      fullscreen: false,
    });
  }

  endLoading() {
    //使用Element loading-close 方法

    this.loading && this.loading.close();
  }

  showFullScreenLoading() {
    if (this.needLoadingRequestCount === 0) {
      this.timer = setTimeout(() => {
        this.startLoading();
      }, 300);
    }

    this.needLoadingRequestCount++;
  }

  tryHideFullScreenLoading() {
    clearTimeout(this.timer);
    if (this.needLoadingRequestCount <= 0) return;
    this.needLoadingRequestCount--;
    if (this.needLoadingRequestCount === 0) {
      this.endLoading();
    }
  }

  /**
   * 导出接口的请求
   */
  async ExportGet(params = {}) {
    try {
      const res = await this.ExportAxios({
        method: "get",
        url: params.url,
        responseType: "arraybuffer",
        headers: {
          Authorization: getToken(),
        },
        params: params.data,
      });

      const blob = new Blob([res.data], {
        type: "application/vnd.ms-excel;charset=utf-8",
      });
      const fileName = params.name + ".xlsx";
      if ("download" in document.createElement("a")) {
        // 非IE下载
        const elink = document.createElement("a");
        elink.download = fileName;
        elink.style.display = "none";
        elink.href = URL.createObjectURL(blob);
        document.body.appendChild(elink);
        elink.click();
        URL.revokeObjectURL(elink.href);
        document.body.removeChild(elink);
      } else {
        navigator.msSaveBlob(blob, fileName);
      }
    } catch (e) {
      throw new Error(`GET请求出错：${e.message}`);
    }
  }

  /**
   * 导出接口的请求
   */
  async ExportPost(params = {}) {
    try {
      const res = await this.ExportAxios({
        method: "post",
        url: params.url,
        responseType: "arraybuffer",
        headers: {
          Authorization: getToken(),
        },
        data: params.data,
      });
      const blob = new Blob([res.data], {
        type: "application/vnd.ms-excel;charset=utf-8",
      });
      const fileName = params.name + ".xlsx";
      if ("download" in document.createElement("a")) {
        // 非IE下载
        const elink = document.createElement("a");
        elink.download = fileName;
        elink.style.display = "none";
        elink.href = URL.createObjectURL(blob);
        document.body.appendChild(elink);
        elink.click();
        URL.revokeObjectURL(elink.href);
        document.body.removeChild(elink);
      } else {
        navigator.msSaveBlob(blob, fileName);
      }
    } catch (e) {
      throw new Error(`GET请求出错：${e.message}`);
    }
  }

  /**
   * get接口的请求
   * @param params
   * @returns {Promise<*|Credential>}
   */
  async get(params = {}) {
    try {
      return await axios.get(params.url, {
        headers: {
          Authorization: getToken(),
          abnormal: params.abnormal || false,
        },
        params: params.data,
        responseType: params.responseType || "",
      });
    } catch (e) {
      throw new Error(`GET请求出错：${e.message}`);
    }
  }

  /**
   * post接口的请求
   * @param params
   * @returns {Promise<*|Credential>}
   */
  async post(params = {}) {
    try {
      return await axios.post(params.url, params.data, {
        headers: {
          "Content-Type": params.contentType
            ? params.contentType
            : "application/json",
          Authorization: getToken(),
          abnormal: params.abnormal || false,
          secret:params.secret?'A27CBC4A669343E382B1EDBBDB5A7149':''
        },
      });
    } catch (e) {
      throw new Error(`POST请求出错：${e.message}`);
    }
  }

  /**
   * delete 接口的请求
   * @param params
   * @returns {Promise<*|Credential>}
   */
  async delete(params = {}) {
    try {
      return await axios.delete(params.url, {
        headers: {
          Authorization: getToken(),
          abnormal: params.abnormal || false,
        },
        params: params.data,
      });
    } catch (e) {
      throw new Error(`DELETE请求出错：${e.message}`);
    }
  }

  /**
   * put 接口的请求
   * @returns {Promise<*|Credential>}
   */
  async put(params = {}) {
    try {
      return await axios.put(params.url, params.data, {
        headers: {
          Authorization: getToken(),
          "Content-Type": params.contentType
            ? params.contentType
            : "application/x-www-form-urlencoded",
          abnormal: params.abnormal || false,
        },
      });
    } catch (e) {
      throw new Error(`PUT：${e.message}`);
    }
  }


  /**
   * tokenPost接口的请求
   * @param params
   * @returns {Promise<*|Credential>}
   */
  async refreshTokenLoginPost(params = {}) {
    try {
      return await this.instance({
        method: "post",
        url: params.url,
        headers: {
          Authorization: utils.TokenAuthorization(),
          "Content-Type": "application/x-www-form-urlencoded",
        },
        data: params.data,
      });
    } catch (e) {
      throw new Error(`POST请求出错：${e.message}`);
    }
  }
  /**
   * 刷新token和登录的响应拦截器
   * @constructor
   */
  tokenPostInterceptors() {
    this.instance.interceptors.response.use(
      (response) => {
        if (response.data.code === 200) {
          return response.data.data;
        } else if (response.config.url !== "provider/authorization/login") {
          store.dispatch("logoUp");
          Message.error("登录已过期~");
          return Promise.reject({ message: "刷新token响应失败~" });
        } else {
          Message.error(response.data.message);
          return Promise.reject({ message: response.data.message });
        }
      },
      function (error) {
        this.pendingRequests = []
        this.isRefreshing = false
        // 对响应错误做点什么
        return Promise.reject(error.response.data);
      }
    );
  }

  /**
   * 添加请求拦截器
   * @constructor
   */
  RequestInterceptors() {
    // 添加请求拦截器

    axios.interceptors.request.use(
      (config) => {
        if (!this.excludeUrls.includes(config.url)) {
          this.showFullScreenLoading();
        }
        return config;
      },
      function (error) {
        // 对请求错误做些什么
        return Promise.reject(error);
      }
    );
  }

  /**
   * 添加响应拦截器
   * @constructor
   */
  ResponseInterceptors() {
    axios.interceptors.response.use(
      (response) => {
        if (!this.excludeUrls.includes(response.config.url))
          this.tryHideFullScreenLoading();
        switch (response.data.code) {
          case 200:
            if (response.config.headers.abnormal) return response.data;
            return response.data.data;
          default:
            if (response.config.headers.abnormal) return response.data;
            Message.error(response.data.message);
            return Promise.reject({ message: response.data.message });
        }
      },
      async (error) => {
        console.log("错误响应", error);
        const errorPar = error.response?.data || {message:error.message}
        // 对响应错误做点什么
        this.tryHideFullScreenLoading();
        if (error.request?.status === 401) {
          const { method, url, params, data, headers } = error.config;
          let dataPr;
          if (method === "get" || method === "delete") {
            dataPr = params;
          } else if (method === "post" || method === "put") {
            dataPr = data;
          }
          const par = {
            url,
            data: dataPr,
            abnormal: headers.abnormal,
            contentType: headers["Content-Type"],
          }
          if ( getrefsToken() ) return await this.refreshToken(method, par)
        } else if (  error.config.headers.abnormal ) {
          return error.config.data
        }
        return Promise.reject(errorPar)
      }
    );
  }


  /**
   * get接口的请求
   * @param params
   * @returns {Promise<*|Credential>}
   */
  async chatGet(params = {}) {
    try {
      return await this.chatAxios.get(params.url, {
        headers: {
          abnormal: params.abnormal || false,
        },
        params: params.data,
        responseType: params.responseType || "",
      });
    } catch (e) {
      throw new Error(`GET请求出错：${e.message}`);
    }
  }

  /**
   * post接口的请求
   * @param params
   * @returns {Promise<*|Credential>}
   */
  async chatPost(params = {}) {
    try {
      return await this.chatAxios.post(params.url, params.data, {
        headers: {
          "Content-Type": params.contentType
            ? params.contentType
            : "application/json",
          abnormal: params.abnormal || false,
        },
      });
    } catch (e) {
      throw new Error(`POST请求出错：${e.message}`);
    }
  }
  /**
   * 添加请求拦截器
   * @constructor
   */
  chatRequestInterceptors() {
    // 添加请求拦截器

    this.chatAxios.interceptors.request.use(
      (config) => {
        return config;

      },
      function (error) {
        // 对请求错误做些什么
        return Promise.reject(error);
      }
    );
  }

  /**
   * 添加响应拦截器
   * @constructor
   */
  chatResponseInterceptors() {
    this.chatAxios.interceptors.response.use(
      (response) => {
        switch (response.data.retcode) {
          case 0:
            if (response.config.headers.abnormal) return response.data;
            return response.data.retdata;
          default:
            if (response.config.headers.abnormal) return response.data;
            Message.error(response.data.retmsg);
            return Promise.reject({ message: response.data.retmsg });
        }
      },
      async (error) => {
        console.log("错误响应", error);
        const errorPar = error.response?.data || {message:error.message}
        // 对响应错误做点什么
        return Promise.reject(errorPar)
      }
    );
  }

  /**
   * 刷新Token
   * @params {Object} params
   * @that this
   */
  async refreshToken(method, params) {
    // 如果正在刷新 token，返回一个 Promise
    if (this.isRefreshing) {
      return new Promise((resolve) => {
        this.pendingRequests.push({ method, params, resolve })
      });
    }

    this.isRefreshing = true

    try {
      const res = await imports.LogoService.refreshToken({
        refreshToken: getrefsToken(),
      });
      let token = "Bearer " + res.accessToken;
      let refsToken = res.refreshToken;
      setToken(token);
      setrefsToken(refsToken);

      switch (method) {
        case "get":
          return await this.get(params);
        case "post":
          return await this.post(params);
        case "delete":
          return await this.delete(params);
        case "put":
          return await this.put(params);
      }
    } catch (error) {
      // 清空请求队列
      this.pendingRequests = []
      throw error
    } finally {
      // 刷新完 token 后，执行所有待处理的请求
      this.pendingRequests.forEach(({ method, params, resolve }) => {
        switch (method) {
          case "get":
            resolve(this.get(params));
            break;
          case "post":
            resolve(this.post(params));
            break;
          case "delete":
            resolve(this.delete(params));
            break;
          case "put":
            resolve(this.put(params));
            break;
        }
      });
      this.pendingRequests = []
      this.isRefreshing = false
    }
  }
}

export default new Axios();
